#include "sessionManager.h"
#include "../log/systemLog/systemLog.h"

#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <stdint.h>

system_error_code_t session_manager_init(session_manager_t *manager, int size)
{
    if (manager == NULL || size <= 0)
    {
        return SYSTEM_ERR_INVALID_ARGUMENT;
    }

    system_error_code_t ret = hash_map_init(&manager->fd_map, size);
    if (ret != SYSTEM_ERR_OK)
    {
        return ret;
    }

    ret = hash_map_init(&manager->username_map, size);
    if (ret != SYSTEM_ERR_OK)
    {
        return ret;
    }

    return SYSTEM_ERR_OK;
}

system_error_code_t session_manager_add_session(session_manager_t *manager, int fd)
{
    if (!manager || fd < 0)
    {
        return SYSTEM_ERR_INVALID_ARGUMENT;
    }

    user_session_t *new_session = (user_session_t *)malloc(sizeof(user_session_t));
    if (!new_session)
    {
        return SYSTEM_ERR_OUT_OF_MEMORY;
    }
    bzero(new_session, sizeof(user_session_t));
    new_session->netfd = fd;
    new_session->state = CONN_STATE_INITIAL; // 设置为初始状态

    // 将指针作为整数存入哈希表
    system_error_code_t ret = hash_map_put(&manager->fd_map, fd, (intptr_t)new_session);
    if (ret != SYSTEM_ERR_OK)
    {
        free(new_session);
        return ret;
    }

    return SYSTEM_ERR_OK;
}

system_error_code_t session_manager_get_session(session_manager_t *manager, int fd, user_session_t **out_session)
{
    if (manager == NULL || out_session == NULL)
    {
        return SYSTEM_ERR_INVALID_ARGUMENT;
    }

    intptr_t session_ptr_val = 0;
    // 从 fd_map 中获取
    system_error_code_t ret = hash_map_get(&manager->fd_map, fd, &session_ptr_val);
    if (ret != SYSTEM_ERR_OK)
    {
        return ret;
    }

    *out_session = (user_session_t *)session_ptr_val;
    return SYSTEM_ERR_OK;
}

system_error_code_t session_manager_register_username(session_manager_t *manager, const char *username, user_session_t *session)
{
    if (manager == NULL || username == NULL || session == NULL)
    {
        return SYSTEM_ERR_INVALID_ARGUMENT;
    }
    // 注意：这里的 key 是字符串地址，不是字符串内容。
    // 这是一个临时的简化实现。
    system_error_code_t ret = hash_map_put(&manager->username_map, (intptr_t)username, (intptr_t)session);
    if (ret != SYSTEM_ERR_OK)
    {
        return ret;
    }
    return SYSTEM_ERR_OK;
}

system_error_code_t session_manager_get_session_by_username(session_manager_t *manager, const char *username, user_session_t **out_session)
{
    if (manager == NULL || username == NULL || out_session == NULL)
    {
        return SYSTEM_ERR_INVALID_ARGUMENT;
    }

    // 这是一个 hack，因为我们的哈希表用 int 作为 key。
    // 我们需要遍历来找到匹配的用户名。
    // 理想情况下，应该使用支持字符串键的哈希表。
    for (int i = 0; i < manager->username_map.size; ++i)
    {
        hash_node_t *node = manager->username_map.buckets[i];
        while (node)
        {
            user_session_t *s = (user_session_t *)node->ring_queue_index; // value
            if (s && strcmp(s->username, username) == 0)
            {
                *out_session = s;
                return SYSTEM_ERR_OK;
            }
            node = node->next;
        }
    }
    return SYSTEM_ERR_SESSION_NOT_FOUND;
}

system_error_code_t session_manager_remove_session(session_manager_t *manager, int fd)
{
    if (manager == NULL)
    {
        return SYSTEM_ERR_INVALID_ARGUMENT;
    }

    user_session_t *session;
    system_error_code_t ret = session_manager_get_session(manager, fd, &session);
    if (ret != SYSTEM_ERR_OK)
    {
        return ret; // 未找到会话或其他错误
    }

    if (session->conn != NULL)
    {
        mysql_close(session->conn); // 使用 mysql_close 释放数据库连接
    }

    // 如果会话中有关联的用户名，说明它可能已注册到 username_map 中，需要移除
    if (strlen(session->username) > 0)
    {
        // 遍历 username_map 查找并移除对应的节点
        for (int i = 0; i < manager->username_map.size; ++i)
        {
            hash_node_t *node = manager->username_map.buckets[i];
            hash_node_t *prev = NULL;
            while (node)
            {
                // 比较节点中存储的 session 指针是否与当前要删除的 session 相同
                if ((user_session_t *)node->ring_queue_index == session)
                {
                    if (prev == NULL)
                    {
                        manager->username_map.buckets[i] = node->next;
                    }
                    else
                    {
                        prev->next = node->next;
                    }
                    free(node);
                    manager->username_map.count--;
                    goto found_and_removed;
                }
                prev = node;
                node = node->next;
            }
        }
    found_and_removed:;
    }

    // 释放会话结构体本身的内存
    free(session);

    // 最后，从 fd_map 中移除
    system_error_code_t remove_ret = hash_map_remove(&manager->fd_map, fd);
    if (remove_ret != SYSTEM_ERR_OK)
    {
        return remove_ret;
    }

    return SYSTEM_ERR_OK;
}